home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
335_04
/
frapsub.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-12-02
|
22KB
|
1,117 lines
/*
HEADER: ;
TITLE: Frankenstein Cross Assemblers;
VERSION: 2.0;
DESCRIPTION: " Reconfigurable Cross-assembler producing Intel (TM)
Hex format object records. ";
SYSTEM: UNIX, MS-Dos ;
FILENAME: frapsub.c ;
WARNINGS: "This software is in the public domain.
Any prior copyright claims are relinquished.
This software is distributed with no warranty whatever.
The author takes no responsibility for the consequences
of its use. " ;
SEE-ALSO: frasmain.c;
AUTHORS: Mark Zenier;
*/
/*
description Parser phase utility routines
History September 1987
September 14, 1990 Dosify, 6 char unique names
*/
#include "fragcon.h"
#include <stdio.h>
#include "frasmdat.h"
#define STRALLOCSZ 4096
local char *currstr;
char * savestring(stx, len)
char *stx;
int len;
/*
description save a character string in permanent (interpass) memory
parameters the string and its length
globals the string pool
return a pointer to the saved string
*/
{
char * rv;
static int savestrleft = 0;
if( savestrleft < (len+1))
{
if((currstr = malloc(STRALLOCSZ)) == (char *)NULL)
{
frafatal("cannot allocate string storage");
}
savestrleft = STRALLOCSZ;
}
savestrleft -= (len+1);
rv = currstr;
for(; len > 0; len--)
*currstr++ = *stx++;
*currstr++ = '\0';
return rv;
}
/* expression node operations */
/* expression tree element */
struct etelem
{
int evs;
int op;
int left, right;
long val;
struct symel *sym;
};
#define NUMENODE INBUFFSZ
struct etelem enode[NUMENODE];
local int nextenode = 1;
/* non general, one exprlist or stringlist per line */
int nextexprs = 0;
int nextstrs = 0;
clrexpr()
/*
description clear out the stuff used for each line
the temporary string pool
the expression tree storage pool
the string and expression lists
*/
{
nextenode = 1;
nextexprs = nextstrs = 0;
}
exprnode(swact, left, op, right, value, symbol)
int swact, left, op, right;
long value;
struct symel * symbol;
/*
description add an element to the expression tree pool
parameters swact, the action performed by the switch in
the polish conversion routine, the category
of the expression node.
left, right the subscripts of the decendent nodes
of the expression tree element
op, the operation to preform
value, a constant value (maybe)
symbol, a pointer to a symbol element (maybe)
globals the next available table element
return the subscript of the expression node
*/
{
if(nextenode >= NUMENODE)
{
frafatal("excessive number of subexpressions");
}
enode [nextenode].evs = swact;
enode [nextenode].left = left;
enode [nextenode].op = op;
enode [nextenode].right = right;
enode [nextenode].val = value;
enode [nextenode].sym = symbol;
return nextenode ++;
}
int nextsymnum = 1;
local struct symel *syallob;
#define SYELPB 512
local int nxtsyel = SYELPB;
struct symel *allocsym()
/*
description allocate a symbol table element, and allocate
a block if the current one is empty. A fatal
error if no more space can be gotten
globals the pointer to the current symbol table block
the count of elements used in the block
return a pointer to the symbol table element
*/
{
if(nxtsyel >= SYELPB)
{
if( (syallob = (struct symel *)calloc(
SYELPB , sizeof(struct symel)))
== (struct symel *)NULL)
{
frafatal("cannot allocate symbol space");
}
nxtsyel = 0;
}
return &syallob[nxtsyel++];
}
#define SYHASHOFF 13
#define SYHASHSZ 1023
int syhash(str)
register char *str;
/*
description produce a hash index from a character string for
the symbol table.
parameters a character string
return an integer related in some way to the character string
*/
{
unsigned rv = 0;
register int offset = 1;
register int c;
while((c = *(str++)) > 0)
{
rv += (c - ' ') * offset;
offset *= SYHASHOFF;
}
return rv % SYHASHSZ;
}
local struct symel * (shashtab[SYHASHSZ]);
static struct symel *getsymslot(str)
char * str;
/*
description find an existing symbol in the symbol table, or
allocate an new element if the symbol doen't exist.
action: hash the string
if there are no symbols for the hash value
create one for this string
otherwise
scan the linked list until the symbol is
found or the end of the list is found
if the symbol was found
exit
if the symbol was not found, allocate and
add at the end of the linked list
fill out the symbol
parameters the character string
globals all the symbol table
return a pointer to the symbol table element for this
character string
*/
{
struct symel *currel, *prevel;
int hv;
if( (currel = shashtab[hv = syhash(str)])
== (struct symel *)NULL)
{
shashtab[hv] = currel = allocsym();
}
else
{
do {
if(strcmp(currel -> symstr, str) == 0)
{
return currel;
}
else
{
prevel = currel;
currel = currel -> nextsym;
}
} while( currel != (struct symel *)NULL);
prevel -> nextsym = currel = allocsym();
}
currel -> symstr = savestring(str, strlen(str));
currel -> nextsym = (struct symel *)NULL;
currel -> tok = 0;
currel -> value = 0;
currel -> seg = SSG_UNUSED;
return currel;
}
struct symel * symbentry(str,toktyp)
char * str;
int toktyp;
/*
description find or add a nonreserved symbol to the symbol table
parameters the character string
the syntactic token type for this charcter string
(this is a parameter so the routine doesn't
have to be recompiled since the yacc grammer
provides the value)
globals the symbol table in all its messy glory
return a pointer to the symbol table element
*/
{
struct symel * rv;
rv = getsymslot(str);
if(rv -> seg == SSG_UNUSED)
{
rv -> tok = toktyp;
rv -> symnum = nextsymnum ++;
rv -> seg = SSG_UNDEF;
}
return rv;
}
void reservedsym(str, tok, value)
char * str;
int tok;
int value;
/*
description add a reserved symbol to the symbol table.
parameters the character string, must be a constant as
the symbol table does not copy it, only point to it.
The syntactic token value.
The associated value of the symbol.
*/
{
struct symel * tv;
tv = getsymslot(str);
if(tv -> seg != SSG_UNUSED)
{
frafatal("cannot redefine reserved symbol");
}
tv -> symnum = 0;
tv -> tok = tok;
tv -> seg = SSG_RESV;
tv -> value = value;
}
buildsymbolindex()
/*
description allocate and fill an array that points to each
nonreserved symbol table element, used to reference
the symbols in the intermediate file, in the output
pass.
globals the symbol table
*/
{
int hi;
struct symel *curr;
if((symbindex = (struct symel **)calloc((unsigned)nextsymnum,
sizeof (struct symel *))) == (struct symel **)NULL)
{
frafatal(" unable to allocate symbol index");
}
for(hi = 0; hi < SYHASHSZ; hi++)
{
if( (curr = shashtab[hi]) != SYMNULL)
{
do {
if( curr -> symnum)
symbindex[curr -> symnum] = curr;
curr = curr -> nextsym;
} while(curr != SYMNULL);
}
}
}
/* opcode symbol table */
#define OPHASHOFF 13
#define OPHASHSZ 1023
local int ohashtab[OPHASHSZ];
setophash()
/*
description set up the linked list hash table for the
opcode symbols
globals the opcode hash table
the opcode table
*/
{
int opn, pl, hv;
/* optab[0] is reserved for the "invalid" entry */
/* opcode subscripts range from 0 to numopcode - 1 */
for(opn = 1; opn < gnumopcode; opn++)
{
hv = opcodehash(optab[opn].opstr);
if( (pl = ohashtab[hv]) == 0)
{
ohashtab[hv] = opn;
}
else
{
while( ophashlnk[pl] != 0)
{
pl = ophashlnk[pl];
}
ophashlnk[pl] = opn;
ophashlnk[opn] = 0;
}
}
}
int findop(str)
char *str;
/*
description find an opcode table subscript
parameters the character string
globals the opcode hash linked list table
the opcode table
return